ASP NET - Cinto de Utilidades

Finalidade

Se algum dia você fez uma página asp net com certeza ou você usou os códigos abaixo ou faltaram os códigos abaixo para que seu site ficasse melhor.

São Subs e Funções de uso geral que implementam recursos muitos deles fundamentais pelo menos visualmente para destacar o site.

A maioria dos recursos abaixo são feitos utilizando CSS ou mesmo o BootStrap. Será informado no código o recurso necessário para que o código funcione.

Página de Login Utilizando recurso GRID do BootStrap

O alinhamento de itens na horizontal sempre foi um problema para os desenvolvedores. Antigamente usávamos uma tabela com colunas de largura definida, mas nem sempre o alinhamento vertical dos itens ficavam bons...muitas vezes a gente tinha que fazer pequenos ajustes para ficar perfeito. Numa tela de login com campos login e senha tinhamos esse problema, na edição de dados de uma tabela com múltiplos campos tínhamos esse problema.

O recurso Grid do Bootstrap divide a tela em 12 partes iguais horizontalmente sendo que podemos fazer, cada coluna, ocupar o espaço de 1 a 12 colunas na mesma linha conforme a nossa necessidade. Esse recurso é particularmente muito interessante quando precisamos emitir uma mensagem seguida de um campo a ser preenchido como numa tela de login ou mesmo numa tela de edição/atualização/inserção de dados.

Este código serve também para páginas HTML como ASP NET.

Código

<p>
            <div class="container" style="width:300px;">
                <h3 class="text-center text-info">Login</h3>

                <div class="row">
                    <div class="col">
                        <asp:Label for="lblmsg" ID="lblmsg" class="text-info" style="color:red;" runat="server" Text=""></asp:Label>
                    </div>
                </div>
                <br />

                <div class="row">
                    <div class="col-2">
                        Login:
                    </div>
                    <div class="col-2">
                        <input type="text" id="txtloginusu" name="txtloginusu" />
                    </div>
                </div>
                <br />

                <div class="row">
                    <div class="col-2">
                        Senha:
                    </div>
                    <div class="col-2">
                        <input type="password" id="txtsenhausu" name="txtsenhausu" />
                    </div>
                </div>
                <br />

                <div class="row" align="center">
                    <div class="col-12">
                        <input type="submit" ID="btnEnviar" Text="Prosseguir" css="btn btn-info btn-md" OnClick="btnEnviar_Click" />
                    </div>
                </div>
            </div>
        </p>

Visual

Login


Login:

Senha:

Explicações

Na tag container coloquei o width=300px para que não ocupasse a tela inteira. Portanto esse código tem que ser colocado dentro de uma container que define seu tamanho.

Para utilizar o grid temos 2 elementos, um para linha e outro para coluna.

div class="row" define uma linha

div class="col" define uma coluna.

A classe col define o espaço de uma coluna. Se eu tiver um controle ou info que ocupe mais de uma coluna posso usar col-2 a col-12 para expandir a coluna onde a info será exibida.

Como disse anteriormente o Grid do Bootstrap divide a tela em 12 partes iguais horizontalmente e isso que faz o alinhamento. A coluna corrente tem uma posição inicial para começar e um tamanho máximo para exibir a informação, se não couber vai para a linha de baixo e a próxima coluna tem uma posição inicial e final definida pelo sistema grid.

Troquei os controles <asp:textbox por <input type=text pelo fato que esta página é html mas o efeito é o mesmo, afinal um textbox asp net é renderizado como uma tag input type text no html.

Formatar GridView

O controle gridview é um dos melhores controles do asp net tanto pela suas funcionalidades como por seus parâmetros que permitem formatar praticamente tudo nele. Contudo são tantos parâmetros que as vezes a gente se perde devido ao fato que um parâmetro mexe com outro e a coisa fica bem confusa.

Como o controle gridview é renderizado como uma table html podemos definir a css para formatar o controle table e suas partes, o header, as colunas e linhas. Abaixo mostro um exemplo de como formatar o cabeçalho e as colunas mas fique a vontade para formatar com o que lhe for melhor.

Código

<style>
        .gridview th{
            font-size: large;
            font-weight: bold;
            color: blue;
            border: 1px solid black;
            padding: 8px;
            background-color:lightblue;
        }

        /* estilo para as celulas da tabela */
        .gridview td{
            padding: 8px;
            border: 1px solid black;
            font-size:small;
        }
    </style>

Gridview - Zebrando

Se você já exibiu um gridview já deve ter tido a necessidade de destacar as linhas de maneira que se uma pessoa percorra horizontalmente seus campos não vá para a linha de cima ou de baixo. Para isto podemos colocar cores diferentes em cada linha, ou seja, as linhas pares de uma cor e as linhas ímpares de outra.

No exemplo abaixo mudo a cor das linhas pares do gridbox fazendo com que as linhas impares fiquem com a mesma cor do fundo da página, mas isto pode ser facilmente modificado colocando um else e outra cor no else para as linhas ímpares. Eu prefiro assim mas varia de site para site.

Public Sub GvZebra()
        Dim a As Integer
        Dim b As Integer

        For a = 0 To gvx.Rows.Count - 1
            For b = 0 To gvx.Rows(a).Cells.Count - 1
                If (a Mod 2) = 0 Then
                    gvx.Rows(a).Cells(b).BackColor = System.Drawing.Color.LightGray
                End If
            Next
        Next
    End Sub

Explicação

O primeiro loop For a = 0 To gvx.Rows.Count - 1 é o loop que percorre todas as linhas do gridview

O segundo loop For b = 0 To gvx.Rows(a).Cells.Count - 1 é o loop que percorre todas as colunas da linha do gridview

O If If (a Mod 2) = 0 Then seleciona as linhas pares (Resto da divisão por 2 igual a zero).

O comando gvx.Rows(a).Cells(b).BackColor possui 2 partes : Rows(a) seleciona a linha e Cells(b) a coluna e backcolor é a cor de fundo que coloquei como cinza claro.

Exportar para o Excel

Exportar o conteúdo do Gridview para o Excel é um desafio especialmente porque as aplicações web usam o código UTF-8 enquanto as aplicações windows usam o código de página 1252 e isso faz com que a acentuação fique completamente bagunçada.

Outra opção é gerar um arquivo csv com as informações e aí baixar o arquivo e ao clicar automaticamente o Excel irá abrir o arquivo. Contudo o mesmo erro de troca de caracteres ocorrerá. O Arquivo CSV usa 2 delimitadores: O código ASCII TAB para separar os campos e o Código ASCII CrLf para separar os registros.

Se você tiver problema com a translação de caracteres procure na Internet pela conversão UTF-8 para 1252. Vai encontrar diversos e a maioria deles utilizando os recursos nativos da plataforma windows.

Código

''' <summary>
    ''' Exige Imports Microsoft.Office.Interop
    ''' </summary>
    ''' <param name="dados"></param>
    Public Sub ExportarParaExcel(dados As GridView)
        If dados.Rows.Count > 0 Then
            Dim XcelApp As New Excel.Application()
            Dim a As Integer

            Try
                a = dados.Rows(0).Cells.Count - 1

                XcelApp.Application.Workbooks.Add(Type.Missing)

                'For i As Integer = 0 To dados.Columns.Count
                'XcelApp.Cells(1, i) = dados.Columns(i - 1).HeaderText
                'Next
                '
                For i As Integer = 0 To dados.Rows.Count - 1
                    For j As Integer = 0 To a
                        'XcelApp.Cells(i + 1, j + 1) = Utf82Windows(dados.Rows(i).Cells(j).Text)
                        XcelApp.Cells(i + 1, j + 1) = dados.Rows(i).Cells(j).Text
                    Next
                Next
                '
                XcelApp.Columns.AutoFit()
                '
                XcelApp.Visible = True
            Catch ex As Exception
                'MessageBox.Show("Erro : " + ex.Message)
                XcelApp.Quit()
            End Try
        End If
    End Sub

Explicação

O Imports Microsoft.Office.Interop é instalado pelo menu Ferramentas, Gerenciador de Pacotes do NuGet, Gerenciar pacotes NuGet para a solução, Procurar, Microsoft.OfficeOffice.InterOp.Excel

Como exemplo abaixo menciono a função Utf82Windows que converte um string de um código para outro.

Public Function Utf82Windows(ByVal Str As String) As String
        'Dim ascii As Encoding = Encoding.GetEncoding("Windows-1252") '"us-ascii" "Windows-1252" não existe: 1252,
        Dim ascii As Encoding = Encoding.ASCII
        Dim unicode As Encoding = Encoding.Unicode

        Dim unicodeBytes As Byte() = unicode.GetBytes(Str)

        Dim asciiBytes As Byte() = Encoding.Convert(unicode, ascii, unicodeBytes)

        Dim asciiChars(ascii.GetCharCount(asciiBytes, 0, asciiBytes.Length) - 1) As Char
        ascii.GetChars(asciiBytes, 0, asciiBytes.Length, asciiChars, 0)
        Dim asciiString As New String(asciiChars)

        Return asciiString
    End Function

PDF-Exibição de um documento pdf

Durante muitos anos esta funcionalidade era feita chamando o Acrobat-Reader ou chamando o shell do Windows para abrir um documento PDF. Como a exibição de um documento PDF estava atrelada a uma aplicação, o documento era exibido corretamente.

Mas hoje o Acrobat Reader ficou enorme, burocrático e muitos não tem um leitor ou usam um leitor de pdf alternativo, como o fox-it.

Neste exemplo utilizo um recurso mais recente e que todo mundo tem instalado na máquina...o web browser. Atualmente todos web-browsers tem o recurso para exibir o documento pdf.

Recurso a ser instalado

Não pergunte como mas o controle web-browser que a gente usa a séculos foi removido dos componentes básicos do Visual Studio. Isso ocorreu porque a Microsoft finalmente desistiu do 'Internet Explorer' e foi para o engine do 'Google Chome' (Chromium).

Sendo assim precisamos instalar o novo recurso e isto é feito entrando no menu ferramentas, Gerenciador de Pacotes do NuGet, Gerenciar Pacotes do NuGet para a solução, aba procurar, na caixa 'Pesquisar' digite 'webview. Quando esta página foi feita o item escolhido foi Microsoft.Web.WebView2 mas se houver outra mais recente, manda pau.

Utilização

Criei um formulário e o chamei de frmWebBrowser. Mudei a propriedade 'windowState' para 'maximized'. Dentro dele coloquei um webView e no docking coloquei para ocupar toda a janela pai ( Fill ).

Código

Private Sub DocumentaçãoToolStripMenuItem_Click(sender As Object, e As EventArgs) Handles DocumentaçãoToolStripMenuItem.Click
        Dim Pasta As String
        Try

            Pasta = Environment.CurrentDirectory 'C:\MinhasPastas\Projetos Visual Studio\MeuProjetox\bin\Debug\net6.0-windows
            Pasta = Strings.Left(Pasta, InStrRev(Pasta, "\") - 1) 'remove net6.0-windows
            Pasta = Strings.Left(Pasta, InStrRev(Pasta, "\") - 1) 'remove Debug
            Pasta = Strings.Left(Pasta, InStrRev(Pasta, "\") - 1) 'remove bin

            Pasta += "\Docs\Manual_Operacional.pdf"

            frmWebBrowser.Show()
            Application.DoEvents()
            Dim uri As New Uri(Pasta)
            frmWebBrowser.WebView21.Source = uri

        Catch ex As Exception
            MsgBox("Erro:" + ex.Message)
        End Try
    End Sub

Explicação

A exibição do item foi invocada por item do menu. Por esse motivo a sub tem esse nome mas pode ser invocado por um clique de um botão ou o que você desejar.
Criei uma variável pasta que apontará para a pasta do documento pdf. Como eu sou um cara organizado coloquei o documento pdf na pasta Docs do meu projeto. O Documento pdf chama-se 'Manual_Operacional.pdf'.

O resultado ao abrir a janela ficou perfeito, muito bom mesmo.

SQL Injection

Quando você tem um site na Internet não pode se dar ao luxo de negligenciar a segurança.

Sql Injection é a adição de códigos maliciosos dentro de um texto que o usuário digita.

Por exemplo, você vai autenticar um usuário e há um textbox com o nome do usuário. Só que ao invés de digitar o nome o usuário digita 'jose;truncate table a.*;da silva'. Se você não tratar o dado digitado, ao concatenar esse string na sua pesquisa e executar no SQL ela vai simplesmente truncar ( eliminar todos os registros ) todas as tabelas que começam com a letra a.

Sendo assim é necessário verificar se não existe algum código malicioso dentro do dado digitado na página. Como cada campo precisa ser verificado o jeito é fazer uma função, em um módulo ou classe, que faça essa verificação. A minha sugestão é:

''' <summary>
  ''' true=problema, encontrado sql injection
  ''' </summary>
  ''' <param name="sql"></param>
  ''' <returns></returns>
  Function sqlInjection(sql As String) As Boolean
      Dim a As String
      a = LCase(sql)
      If InStr(a, "drop") <> 0 Then Return True
      If InStr(a, "select") <> 0 Then Return True
      If InStr(a, "update") <> 0 Then Return True
      If InStr(a, "truncate") <> 0 Then Return True
      If InStr(a, "insert") <> 0 Then Return True
      If InStr(a, "alter") <> 0 Then Return True
      If InStr(a, "begin") <> 0 Then Return True
      If InStr(a, "break") <> 0 Then Return True
      If InStr(a, "checkpoint") <> 0 Then Return True
      If InStr(a, "commit") <> 0 Then Return True
      If InStr(a, "create") <> 0 Then Return True
      If InStr(a, "cursor") <> 0 Then Return True
      If InStr(a, "dbcc") <> 0 Then Return True
      If InStr(a, "deny") <> 0 Then Return True
      If InStr(a, "drop") <> 0 Then Return True
      If InStr(a, "escape") <> 0 Then Return True
      If InStr(a, "exec") <> 0 Then Return True
      If InStr(a, "execute") <> 0 Then Return True
      If InStr(a, "insert") <> 0 Then Return True
      If InStr(a, ";go") <> 0 Then Return True
      If InStr(a, "go;") <> 0 Then Return True
      If InStr(a, "grant") <> 0 Then Return True
      If InStr(a, "opendatasource") <> 0 Then Return True
      If InStr(a, "openquery") <> 0 Then Return True
      If InStr(a, "openrowset") <> 0 Then Return True
      If InStr(a, "shutdown") <> 0 Then Return True
      If InStr(a, "sp_") <> 0 Then Return True
      If InStr(a, "tran") <> 0 Then Return True
      If InStr(a, "transaction") <> 0 Then Return True
      If InStr(a, "update") <> 0 Then Return True
      If InStr(a, "while") <> 0 Then Return True
      If InStr(a, "xp_") <> 0 Then Return True
      If InStr(a, ";") <> 0 Then Return True
      If InStr(a, "--") <> 0 Then Return True

      Return False
  End Function


A função acima é rigorosa porque não permite sequer um ; o que separaria um comando de outro no sql. Contudo você pode 'personalizar' para ficar como necessite mas alerto para um risco de segurança em potencial.